#!/bin/bash

KDUMP_CONFIG_FILE="/etc/kdump.conf"

# Read from kdump config file stripping all comments
read_strip_comments()
{
    # strip heading spaces, and print any content starting with
    # neither space or #, and strip everything after #
    sed -n -e "s/^\s*\([^# \t][^#]\+\).*/\1/gp" $1
}

strip_comments()
{
    echo $@ | sed -e 's/\(.*\)#.*/\1/'
}

# get_option_value <option_name>
# retrieves value of option defined in kdump.conf
get_option_value() {
    strip_comments `grep "^$1[[:space:]]\+" /etc/kdump.conf | tail -1 | cut -d\  -f2-`
}

check_failure_action_config()
{
	local default_option
	local failure_action
	local option="failure_action"

	default_option=$(awk '$1 ~ /^default$/ {print $2;}' $KDUMP_CONFIG_FILE)
	failure_action=$(awk '$1 ~ /^failure_action$/ {print $2;}' $KDUMP_CONFIG_FILE)

	if [ -z "$failure_action" -a -z "$default_option" ]; then
		return 0
	elif [ -n "$failure_action" -a -n "$default_option" ]; then
		echo "Cannot specify 'failure_action' and 'default' option together"
		return 1
	fi

	if [ -n "$default_option" ]; then
		option="default"
		failure_action="$default_option"
	fi

	case "$failure_action" in
	  reboot|halt|poweroff|shell|dump_to_rootfs)
		return 0
	  ;;
	  *)
		echo $"Usage kdump.conf: $option {reboot|halt|poweroff|shell|dump_to_rootfs}"
		return 1
	esac
}

check_final_action_config()
{
	local final_action

	final_action=$(awk '$1 ~ /^final_action$/ {print $2;}' $KDUMP_CONFIG_FILE)
	if [ -z "$final_action" ]; then
		return 0
	else
		case "$final_action" in
		  reboot|halt|poweroff)
			return 0
		  ;;
		  *)
			echo $"Usage kdump.conf: final_action {reboot|halt|poweroff}"
			return 1
		esac
	fi
}

check_fence_kdump_config()
{
	local hostname=`hostname`
	local ipaddrs=`hostname -I`
	local nodes=$(get_option_value "fence_kdump_nodes")

	for node in $nodes; do
		if [ "$node" = "$hostname" ]; then
			echo "Option fence_kdump_nodes cannot contain $hostname"
			return 1
		fi
		# node can be ipaddr
		echo $ipaddrs | grep $node > /dev/null
		if [ $? -eq 0 ]; then
			echo "Option fence_kdump_nodes cannot contain $node"
			return 1
		fi
	done

	return 0
}

check_kdump_config()
{
        local nr

        nr=$(awk 'BEGIN{cnt=0} /^raw|^ssh[[:blank:]]|^nfs|^ext[234]|^xfs|^btrfs|^minix|^dracut_args .*\-\-mount/{cnt++} END{print cnt}' $KDUMP_CONFIG_FILE)
        [ $nr -gt 1 ] && {
                echo "More than one dump targets specified."
                return 1
        }

        nr=$(grep "^dracut_args .*\-\-mount" $KDUMP_CONFIG_FILE | grep -o "\-\-mount" | wc -l)
        [ $nr -gt 1 ] && {
                echo "Multiple mount targets specified in one \"dracut_args\"."
                return 1
        }

        # Check if we have any leading spaces (or tabs) before the
        # variable name in the kdump conf file
        if grep -E -q '^[[:blank:]]+[a-z]' $KDUMP_CONFIG_FILE; then
                echo "No whitespaces are allowed before a kdump option name in $KDUMP_CONFIG_FILE"
                return 1
        fi

        while read config_opt config_val; do
                case "$config_opt" in
                \#* | "")
                        ;;
                raw|ext2|ext3|ext4|minix|btrfs|xfs|nfs|ssh|sshkey|path|core_collector|kdump_post|kdump_pre|extra_bins|extra_modules|default|force_rebuild|force_no_rebuild|dracut_args|fence_kdump_args|fence_kdump_nodes)
                        [ -z "$config_val" ] && {
                                echo "Invalid kdump config value for option $config_opt."
                                return 1;
                        }
                        if [ -d "/proc/device-tree/ibm,opal/dump" ] && [ "$config_opt" == "raw" ]; then
				                  echo "WARNING: Won't capture opalcore when 'raw' dump target is used."
			                  fi
                        ;;
                net|options|link_delay|disk_timeout|debug_mem_level|blacklist)
                        echo "Deprecated kdump config option: $config_opt. Refer to kdump.conf manpage for alternatives."
                        return 1
                        ;;
                *)
                        echo "Invalid kdump config option $config_opt"
                        return 1;
                        ;;
                esac
        done <<< "$(read_strip_comments $KDUMP_CONFIG_FILE)"

        check_failure_action_config || return 1
        check_final_action_config || return 1
        check_fence_kdump_config || return 1

        return 0
}


check_kdump_status(){
  systemctl status kdump >/dev/null
  return $?
}

ops_run(){
	check_kdump_status
	if [ $? -ne 0 ]; then
	  check_kdump_config
	  if [ $? -ne 0 ]; then
	    echo "/etc/kdump.conf check fails, /etc/kdump.conf will be overwritten with default configuration, old configuration is archived in /etc/kdump.conf.old"
	    cp /etc/kdump.conf /etc/kdump.conf.old
	    cp -f /usr/lib/opencloudos-tools/ops/kdump/kdump.conf /etc/kdump.conf
	    systemctl restart kdump >/dev/null
	    if [ $? -ne 0 ]; then
	      echo 'The kdump service status is abnormal after restart, configuration check is passed, there may be other reasons for the service failure, See "systemctl status kdump.service" and "journalctl -xe" for details.'
	      return 1
	    fi
	    echo "The kdump service status is normal with default conf."
	    return 0
	  fi
	  systemctl restart kdump >/dev/null
	  if [ $? -ne 0 ]; then
	      echo 'The kdump service status is abnormal, configuration check is passed, there may be other reasons for the service failure, See "systemctl status kdump.service" and "journalctl -xe" for details.'
	      return 1
	  fi
	    fi
	echo "kdump service is normal."
	return 0
}

ops_run
